<!doctype html>
<html class="theme-next   use-motion ">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />












  <link href="/vendors/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"/>




  <link href="//fonts.googleapis.com/css?family=Lato:300,400,700,400italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">



<link href="/vendors/font-awesome/css/font-awesome.min.css?v=4.4.0" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=0.4.5.2" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="blocks,concurrency,java," />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=0.4.5.2" />






<meta name="description" content="Threads often have to coordinate their actions. The most common coordination idiom is the guarded block Such a block begins by polling a condition that must be true before the block can proceed, There">
<meta property="og:type" content="article">
<meta property="og:title" content="Guarded Blocks">
<meta property="og:url" content="https://lechance.github.io/posts/2016/04/02/guarded-blocks/index.html">
<meta property="og:site_name" content="Lechance's Blog">
<meta property="og:description" content="Threads often have to coordinate their actions. The most common coordination idiom is the guarded block Such a block begins by polling a condition that must be true before the block can proceed, There">
<meta property="og:updated_time" content="2016-08-04T07:17:41.179Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Guarded Blocks">
<meta name="twitter:description" content="Threads often have to coordinate their actions. The most common coordination idiom is the guarded block Such a block begins by polling a condition that must be true before the block can proceed, There">



<script type="text/javascript" id="hexo.configuration">
  var CONFIG = {
    scheme: '',
    sidebar: 'hide',
    motion: true
  };
</script>

  <title> Guarded Blocks | Lechance's Blog </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="en">

  <!--[if lte IE 8]>
  <div style=' clear: both; height: 59px; padding:0 0 0 15px; position: relative;margin:0 auto;'>
    <a href="http://windows.microsoft.com/en-US/internet-explorer/products/ie/home?ocid=ie6_countdown_bannercode">
      <img src="http://7u2nvr.com1.z0.glb.clouddn.com/picouterie.jpg" border="0" height="42" width="820"
           alt="You are using an outdated browser. For a faster, safer browsing experience, upgrade for free today or use other browser ,like chrome firefox safari."
           style='margin-left:auto;margin-right:auto;display: block;'/>
    </a>
  </div>
<![endif]-->
  


<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
            (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'UA-75174040-1', 'auto');
  ga('send', 'pageview');
</script>


  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?5641a55459d47b98c90f424b8ca53a5a";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




  <div class="container one-column page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-meta ">
  

  <div class="custom-logo-site-title">
    <a href="/"  class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <span class="site-title">Lechance's Blog</span>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>
  <p class="site-subtitle"></p>
</div>

<div class="site-nav-toggle">
  <button>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
    <span class="btn-bar"></span>
  </button>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu ">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-home fa-fw"></i> <br />
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-archive fa-fw"></i> <br />
            
            Archives
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags" rel="section">
            
              <i class="menu-item-icon fa fa-tags fa-fw"></i> <br />
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-links">
          <a href="/links" rel="section">
            
              <i class="menu-item-icon fa fa-link fa-fw"></i> <br />
            
            Links
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-user fa-fw"></i> <br />
            
            About
          </a>
        </li>
      
        
        <li class="menu-item menu-item-rss">
          <a href="/atom.xml" rel="section">
            
              <i class="menu-item-icon fa fa-rss fa-fw"></i> <br />
            
            Rss
          </a>
        </li>
      

      
      
    </ul>
  

  
</nav>

 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div id="content" class="content">
          

  <div id="posts" class="posts-expand">
    

  
  

  
  
  

  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                Guarded Blocks
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            Posted on
            <time itemprop="dateCreated" datetime="2016-04-02T16:22:43+08:00" content="2016-04-02">
              2016-04-02
            </time>
          </span>

          
            <span class="post-category" >
              &nbsp; | &nbsp; In
              
                <span itemprop="about" itemscope itemtype="https://schema.org/Thing">
                  <a href="/categories/Java/" itemprop="url" rel="index">
                    <span itemprop="name">Java</span>
                  </a>
                </span>

                
                
                  , 
                

              
                <span itemprop="about" itemscope itemtype="https://schema.org/Thing">
                  <a href="/categories/Java/Tutorial/" itemprop="url" rel="index">
                    <span itemprop="name">Tutorial</span>
                  </a>
                </span>

                
                
                  , 
                

              
                <span itemprop="about" itemscope itemtype="https://schema.org/Thing">
                  <a href="/categories/Java/Tutorial/Concurrency/" itemprop="url" rel="index">
                    <span itemprop="name">Concurrency</span>
                  </a>
                </span>

                
                

              
            </span>
          

          
            
              <span class="post-comments-count">
                &nbsp; | &nbsp;
                <a href="/posts/2016/04/02/guarded-blocks/#comments" itemprop="discussionUrl">
                  <span class="post-comments-count ds-thread-count" data-thread-key="posts/2016/04/02/guarded-blocks/" itemprop="commentsCount"></span>
                </a>
              </span>
            
          

          
		  
		  
			 &nbsp; | &nbsp;
			 <span id="/posts/2016/04/02/guarded-blocks/"class="leancloud_visitors"  data-flag-title="Guarded Blocks">
             &nbsp;Views
            </span>
		  
		
        </div>
      </header>
    


    <div class="post-body">

      
      

      
        <span itemprop="articleBody"><p>Threads often have to coordinate their actions. The most common coordination idiom is the <code>guarded block</code> Such a block begins by polling a condition that must be true before the block can proceed, There are a number of steps to follow in order to do this correctly.</p>
<p>Suppose, for example, <code>guardedJoy</code> is a method that must not proceed until a shared variable <code>joy</code> has been set by another thread. Such a method could, in theory, simply loop until condition is satisfied, but that loop is wasteful, since it executes continuously while waiting.</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">guardedJoy</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">//simple loop guard. Wastes processor time. Don't do this!</span></span><br><span class="line">    <span class="keyword">while</span>(!joy)&#123;&#125;</span><br><span class="line">    System.out.println(<span class="string">"Joy has been achieved!"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>A more efficient guard invokes <code>Object.wait</code> to suspend the current thread. The invocation of <code>wait</code> does not return until another thread has issued a notification that some special event may have occurred - though not necessarily the event this thread is waiting for:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">guardedJoy</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">//This guard only loops once for each special event, which may not be the event we're waiting for.</span></span><br><span class="line">    <span class="keyword">while</span>(!joy)&#123;</span><br><span class="line">	<span class="keyword">try</span>&#123;</span><br><span class="line">	    wait();</span><br><span class="line">	&#125;<span class="keyword">catch</span>(InterruptedException e)&#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    System.out.println(<span class="string">"Joy and efficiency have been archieved!"</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>Note: Always invoke <code>wait</code> inside a loop that tests for the condition being waited for. Don’t assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.</p>
</blockquote>
<p>Like many methods that suspend execution, <code>wait</code> can thow <code>InterruptedException</code> Exception. In this example, we can just ignore that exception – we only care about the value of <code>joy</code>.</p>
<p>Why is this version of <code>guardedJoy</code> synchronized? Suppose <code>d</code> is the object we’re using to invoke <code>wait</code>. When a thread invoked <code>d.wait</code>, it must own the intrinsic lock for <code>d</code> – otherwise an error is thrown. Invoking <code>wait</code> inside a synchronized method is a simple way to acquire the intrinsic lock.</p>
<p>When <code>wait</code> is invoked, the thread releases the lock and suspends execution. At some future time, another thread will acquire the same lock and invoke <code>Object.notifyAll</code>, informing all  threads waiting on that lock that something important has happened:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="title">notifyJoy</span><span class="params">()</span></span>&#123;</span><br><span class="line">	joy = <span class="keyword">true</span>;</span><br><span class="line">	notifyAll();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>Some time after second thread has released the lock, the first thread reacquires the lock and resumes by returning from the invocation of wait.</p>
<hr>
<h2 id="Note:_There_is_a_second_notification_method,_notify,_which_wakes_up_a_single_thread-_Because_notify_doesn’t_allow_you_to_specify_the_thread_that_is_woken_up,_it_is_useful_only_in_massively_parallel_applications_-_that_is,_programs_with_a_large_number_of_threads,_all_doing_similar_chores-_In_such_an_application,_you_don’t_care_which_thread_gets_woken_up-"><em>Note</em>: There is a second notification method, <code>notify</code>, which wakes up a single thread. Because <code>notify</code> doesn’t allow you to specify the thread that is woken up, it is useful only in massively parallel applications - that is, programs with a large number of threads, all doing similar chores. In such an application, you don’t care which thread gets woken up.</h2><p>Let’s use guarded blocks to create a <code>Producer-Consumer</code> application. This kind of application shares data between two threads: the <code>producer</code>, that creates the data, and the <code>consumer</code>, that does something with it. The two threads communicate using a shared object. Coordination is essential: the consumer thread must not attempt to retrieve the data before the producer thread has delivered it, and the producer thread must not attempt to deliver new data if the consumer hasn’t retireve the old data.</p>
<p>In this example, the data is a series of text messages, which are shared through an object of type <em>Drop</em>:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Drop</span></span>&#123;</span><br><span class="line">	<span class="comment">//message sent from producer to consumer</span></span><br><span class="line">	<span class="keyword">private</span> Stirng message;</span><br><span class="line">	<span class="comment">//True if consumer should wait for producer to send message, false if producer should wait for consumer to retrieve message</span></span><br><span class="line">	<span class="keyword">private</span> <span class="keyword">boolean</span> empty = <span class="keyword">true</span>;</span><br><span class="line">	</span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> String <span class="title">take</span><span class="params">()</span></span>&#123;</span><br><span class="line">		<span class="comment">//wait until message is available</span></span><br><span class="line">		<span class="keyword">while</span>(empty)&#123;</span><br><span class="line">			<span class="keyword">try</span>&#123;</span><br><span class="line">			wait();</span><br><span class="line">			&#125;<span class="keyword">catch</span>(InterruptedException e)&#123;&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="comment">//Toggle status</span></span><br><span class="line">		empty = <span class="keyword">true</span>;</span><br><span class="line">		<span class="comment">//notify producer that status has changed</span></span><br><span class="line">		notifyAll();</span><br><span class="line">		<span class="keyword">return</span> message;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title">put</span><span class="params">(String message)</span></span>&#123;</span><br><span class="line">		<span class="comment">//wait until message has been retrieved</span></span><br><span class="line">		<span class="keyword">while</span>(!empty)&#123;</span><br><span class="line">			<span class="keyword">try</span>&#123;</span><br><span class="line">			wait();</span><br><span class="line">			&#125;<span class="keyword">catch</span>(InterruptedException e)&#123;&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="comment">//Toggle status</span></span><br><span class="line">		empty = <span class="keyword">false</span>;</span><br><span class="line">		<span class="comment">//Store message </span></span><br><span class="line">		<span class="keyword">this</span>.message = message;</span><br><span class="line">		<span class="comment">//Notify consumer that status has changed</span></span><br><span class="line">		notifyAll();</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>The producer thread send a series of fimilar messages, The String “DONE” indicates that all messages have been sent. To simulate the unpredictable nature of real-world applications, the producer thread pauses for random intervals between messages.</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.Random;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">producer</span> <span class="keyword">implements</span> <span class="title">Runnable</span></span>&#123;</span><br><span class="line">	<span class="keyword">private</span> Drop drop;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="title">Producer</span><span class="params">(Drop drop)</span></span>&#123;</span><br><span class="line">		<span class="keyword">this</span>.drop = drop;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;</span><br><span class="line">		String importantInfo[] =&#123;</span><br><span class="line">		<span class="string">"Mares eat oats"</span>,</span><br><span class="line">		<span class="string">"Does eat oats"</span>,</span><br><span class="line">		<span class="string">"Little lambs eat ivy"</span>,</span><br><span class="line">		<span class="string">"a kid will eat ivy too"</span></span><br><span class="line">		&#125;</span><br><span class="line">		Random random = <span class="keyword">new</span> Random();</span><br><span class="line"></span><br><span class="line">		<span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; importantInfo.length; i++)&#123;</span><br><span class="line">			drop.put(importantInfo[i]);</span><br><span class="line">			<span class="keyword">try</span>&#123;</span><br><span class="line">				Thread.sleep(random.nextInt(<span class="number">5000</span>));</span><br><span class="line">			&#125;<span class="keyword">catch</span>(InterruptedException e)&#123;&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		drop.put(<span class="string">"DONE"</span>);</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</span>
      
    </div>

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/blocks/" rel="tag">#blocks</a>
          
            <a href="/tags/concurrency/" rel="tag">#concurrency</a>
          
            <a href="/tags/java/" rel="tag">#java</a>
          
        </div>
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/posts/2016/03/28/intrinsic-locks-and-synchronization/" rel="next" title="Intrinsic Locks and Synchronization">
                <i class="fa fa-chevron-left"></i> Intrinsic Locks and Synchronization
              </a>
            
          </div>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/posts/2016/04/02/usage-of-volley-lib/" rel="prev" title="Usage of The Volley Library in Android">
                Usage of The Volley Library in Android <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
        <div class="ds-share flat" data-thread-key="posts/2016/04/02/guarded-blocks/"
     data-title="Guarded Blocks"
     data-content=""
     data-url="https://lechance.github.io/posts/2016/04/02/guarded-blocks/">
  <div class="ds-share-inline">
    <ul  class="ds-share-icons-16">

      <li data-toggle="ds-share-icons-more"><a class="ds-more" href="javascript:void(0);">分享到：</a></li>
      <li><a class="ds-weibo" href="javascript:void(0);" data-service="weibo">微博</a></li>
      <li><a class="ds-qzone" href="javascript:void(0);" data-service="qzone">QQ空间</a></li>
      <li><a class="ds-qqt" href="javascript:void(0);" data-service="qqt">腾讯微博</a></li>
      <li><a class="ds-wechat" href="javascript:void(0);" data-service="wechat">微信</a></li>

    </ul>
    <div class="ds-share-icons-more">
    </div>
  </div>
</div>
      
    </div>
  </div>


        </div>

        


        
  <div class="comments" id="comments">
    
      <div class="ds-thread" data-thread-key="posts/2016/04/02/guarded-blocks/"
           data-title="Guarded Blocks" data-url="https://lechance.github.io/posts/2016/04/02/guarded-blocks/">
      </div>
    
  </div>


      </div>

      
        
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            Table Of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            Overview
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel ">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" src="/upload/image/avatar.png" alt="Lechance Cheung" itemprop="image"/>
          <p class="site-author-name" itemprop="name">Lechance Cheung</p>
        </div>
        <p class="site-description motion-element" itemprop="description">The code to change the world</p>
        <nav class="site-state motion-element">
          <div class="site-state-item site-state-posts">
            <a href="/archives">
              <span class="site-state-item-count">43</span>
              <span class="site-state-item-name">posts</span>
            </a>
          </div>

          <div class="site-state-item site-state-categories">
            
              <span class="site-state-item-count">15</span>
              <span class="site-state-item-name">categories</span>
              
          </div>

          <div class="site-state-item site-state-tags">
            <a href="/tags">
              <span class="site-state-item-count">66</span>
              <span class="site-state-item-name">tags</span>
              </a>
          </div>

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="http://weibo.com/lechance" target="_blank">
                  
                    <i class="fa fa-weibo"></i> Weibo
                  
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://github.com/lechance" target="_blank">
                  
                    <i class="fa fa-globe"></i> Github
                  
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://guides.github.com/features/mastering-markdown/" target="_blank">
                  
                    <i class="fa fa-globe"></i> MD CheatSheet
                  
                </a>
              </span>
            
          
        </div>

        
        
          <div class="cc-license motion-element" itemprop="license">
            <a href="http://creativecommons.org/licenses/by-nc-sa/4.0" class="cc-opacity" target="_blank">
              <img src="/images/cc-by-nc-sa.svg" alt="Creative Commons" />
            </a>
          </div>
        

        <div class="links-of-author motion-element">
          
            <p class="site-author-name">Common Sites</p>
            
              <span class="links-of-author-item">
                <a href="https://developers.google.cn" target="_blank">Google Developers</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://androidweekly.net/archive" target="_blank">Android Weekly</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://rxjava.yuxingxin.com" target="_blank">RxJava Essentials</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://hc.apache.org/index.html" target="_blank">Http Components</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://simpledeveloper.com" target="_blank">Simple Developer</a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.ibm.com/developerworks/library" target="_blank">IBM(Technical Library)</a>
              </span>
            
          
        </div>

      </section>

      
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc-indicator-top post-toc-indicator">
            <i class="fa fa-angle-double-up"></i>
          </div>
          <div class="post-toc">
            
              
            
            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Note:_There_is_a_second_notification_method,_notify,_which_wakes_up_a_single_thread-_Because_notify_doesn’t_allow_you_to_specify_the_thread_that_is_woken_up,_it_is_useful_only_in_massively_parallel_applications_-_that_is,_programs_with_a_large_number_of_threads,_all_doing_similar_chores-_In_such_an_application,_you_don’t_care_which_thread_gets_woken_up-"><span class="nav-number">1.</span> <span class="nav-text">Note: There is a second notification method, notify, which wakes up a single thread. Because notify doesn’t allow you to specify the thread that is woken up, it is useful only in massively parallel applications - that is, programs with a large number of threads, all doing similar chores. In such an application, you don’t care which thread gets woken up.</span></a></li></ol></div>
            
          </div>
          <div class="post-toc-indicator-bottom post-toc-indicator">
            <i class="fa fa-angle-double-down"></i>
          </div>
        </section>
      

    </div>
  </aside>


      
    </main>

    <footer id="footer" class="footer">
      <div class="google-ad">
	  <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- myblogfootergooglead -->
<ins class="adsbygoogle"
     style="display:inline-block;width:468px;height:60px"
     data-ad-client="ca-pub-6226577131784709"
     data-ad-slot="6824128270"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>

      </div>
      <div class="footer-inner">
        <script async src="https://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
</script>

<div class="copyright" >
  
  &copy;  2015 - 
  <span itemprop="copyrightYear">2017</span>
  <span class="with-love">
    <i class="icon-next-heart fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Lechance Cheung</span>
</div>

<div class="powered-by">
  Powered by <a class="theme-link" href="http://hexo.io">Hexo</a>
</div>

<div class="theme-info">
  Theme -
  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
    NexT
  </a>
</div>

<span id="busuanzi_container_site_pv">
  &nbsp; | &nbsp;PV <span id="busuanzi_value_site_pv"></span> &nbsp;| &nbsp;UV <span id="busuanzi_value_site_uv"></span>
</span>



      </div>
    </footer>

    <div class="back-to-top"></div>
  </div>

  <script type="text/javascript" src="/vendors/jquery/index.js?v=2.1.3"></script>

  
  

  
    

  
    
  

  <script type="text/javascript">
    var duoshuoQuery = {short_name:"lechance"};
    (function() {
      var ds = document.createElement('script');
      ds.type = 'text/javascript';ds.async = true;
      ds.id = 'duoshuo-script';
      ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//lechance.github.io/embed_ua.js';
      ds.charset = 'UTF-8';
      (document.getElementsByTagName('head')[0]
      || document.getElementsByTagName('body')[0]).appendChild(ds);
    })();
  </script>
    
     


    
  

  
  <script type="text/javascript" src="/vendors/fancybox/source/jquery.fancybox.pack.js"></script>
  <script type="text/javascript" src="/js/fancy-box.js?v=0.4.5.2"></script>


  <script type="text/javascript" src="/js/helpers.js?v=0.4.5.2"></script>
  <script type="text/javascript" src="/vendors/velocity/velocity.min.js"></script>
<script type="text/javascript" src="/vendors/velocity/velocity.ui.min.js"></script>

<script type="text/javascript" src="/js/motion.js?v=0.4.5.2" id="motion.global"></script>


  <script type="text/javascript" src="/vendors/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  <script type="text/javascript" src="/vendors/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  
<script type="text/javascript" src="/js/bootstrap.scrollspy.js?v=0.4.5.2" id="bootstrap.scrollspy.custom"></script>


<script type="text/javascript" id="sidebar.toc.highlight">
  $(document).ready(function () {
    var tocSelector = '.post-toc';
    var $tocSelector = $(tocSelector);
    var activeCurrentSelector = '.active-current';

    $tocSelector
      .on('activate.bs.scrollspy', function () {
        var $currentActiveElement = $(tocSelector + ' .active').last();

        removeCurrentActiveClass();
        $currentActiveElement.addClass('active-current');

        $tocSelector[0].scrollTop = $currentActiveElement.position().top;
      })
      .on('clear.bs.scrollspy', function () {
        removeCurrentActiveClass();
      });

    function removeCurrentActiveClass () {
      $(tocSelector + ' ' + activeCurrentSelector)
        .removeClass(activeCurrentSelector.substring(1));
    }

    function processTOC () {
      getTOCMaxHeight();
      toggleTOCOverflowIndicators();
    }

    function getTOCMaxHeight () {
      var height = $('.sidebar').height() -
                   $tocSelector.position().top -
                   $('.post-toc-indicator-bottom').height();

      $tocSelector.css('height', height);

      return height;
    }

    function toggleTOCOverflowIndicators () {
      tocOverflowIndicator(
        '.post-toc-indicator-top',
        $tocSelector.scrollTop() > 0 ? 'show' : 'hide'
      );

      tocOverflowIndicator(
        '.post-toc-indicator-bottom',
        $tocSelector.scrollTop() >= $tocSelector.find('ol').height() - $tocSelector.height() ? 'hide' : 'show'
      )
    }

    $(document).on('sidebar.motion.complete', function () {
      processTOC();
    });

    $('body').scrollspy({ target: tocSelector });
    $(window).on('resize', function () {
      if ( $('.sidebar').hasClass('sidebar-active') ) {
        processTOC();
      }
    });

    onScroll($tocSelector);

    function onScroll (element) {
      element.on('mousewheel DOMMouseScroll', function (event) {
          var oe = event.originalEvent;
          var delta = oe.wheelDelta || -oe.detail;

          this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
          event.preventDefault();

          toggleTOCOverflowIndicators();
      });
    }

    function tocOverflowIndicator (indicator, action) {
      var $indicator = $(indicator);
      var opacity = action === 'show' ? 1 : 0;
      $indicator.velocity ?
        $indicator.velocity('stop').velocity({
          opacity: opacity
        }, { duration: 100 }) :
        $indicator.stop().animate({
          opacity: opacity
        }, 100);
    }

  });
</script>

<script type="text/javascript" id="sidebar.nav">
  $(document).ready(function () {
    var html = $('html');
    var TAB_ANIMATE_DURATION = 200;
    var hasVelocity = $.isFunction(html.velocity);

    $('.sidebar-nav li').on('click', function () {
      var item = $(this);
      var activeTabClassName = 'sidebar-nav-active';
      var activePanelClassName = 'sidebar-panel-active';
      if (item.hasClass(activeTabClassName)) {
        return;
      }

      var currentTarget = $('.' + activePanelClassName);
      var target = $('.' + item.data('target'));

      hasVelocity ?
        currentTarget.velocity('transition.slideUpOut', TAB_ANIMATE_DURATION, function () {
          target
            .velocity('stop')
            .velocity('transition.slideDownIn', TAB_ANIMATE_DURATION)
            .addClass(activePanelClassName);
        }) :
        currentTarget.animate({ opacity: 0 }, TAB_ANIMATE_DURATION, function () {
          currentTarget.hide();
          target
            .stop()
            .css({'opacity': 0, 'display': 'block'})
            .animate({ opacity: 1 }, TAB_ANIMATE_DURATION, function () {
              currentTarget.removeClass(activePanelClassName);
              target.addClass(activePanelClassName);
            });
        });

      item.siblings().removeClass(activeTabClassName);
      item.addClass(activeTabClassName);
    });

    $('.post-toc a').on('click', function (e) {
      e.preventDefault();
      var targetSelector = escapeSelector(this.getAttribute('href'));
      var offset = $(targetSelector).offset().top;
      hasVelocity ?
        html.velocity('stop').velocity('scroll', {
          offset: offset  + 'px',
          mobileHA: false
        }) :
        $('html, body').stop().animate({
          scrollTop: offset
        }, 500);
    });

    // Expand sidebar on post detail page by default, when post has a toc.
    motionMiddleWares.sidebar = function () {
      var $tocContent = $('.post-toc-content');
      if (CONFIG.sidebar === 'post') {
        if ($tocContent.length > 0 && $tocContent.html().trim().length > 0) {
          displaySidebar();
        }
      }
    };
  });
</script>



  <script type="text/javascript" src="/js/bootstrap.js"></script>

  
  

  
  
  
  
  	 <!-- custom analytics part create by xiamo -->
<script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
<script>AV.initialize("cHqcCBDQtcbkltuUTyplEYWJ-gzGzoHsz", "SkioJGixXR48ACpgA0W2lOWd");</script>
<script>
function showTime(Counter) {
	var query = new AV.Query(Counter);
	$(".leancloud_visitors").each(function() {
		var url = $(this).attr("id").trim();
		query.equalTo("url", url);
		query.find({
			success: function(results) {
				if (results.length == 0) {
					var content = '0 ' + $(document.getElementById(url)).text();
					$(document.getElementById(url)).text(content);
					return;
				}
				for (var i = 0; i < results.length; i++) {
					var object = results[i];
					var content = object.get('time') + ' ' + $(document.getElementById(url)).text();
					$(document.getElementById(url)).text(content);
				}
			},
			error: function(object, error) {
				console.log("Error: " + error.code + " " + error.message);
			}
		});

	});
}

function addCount(Counter) {
	var Counter = AV.Object.extend("Counter");
	url = $(".leancloud_visitors").attr('id').trim();
	title = $(".leancloud_visitors").attr('data-flag-title').trim();
	var query = new AV.Query(Counter);
	query.equalTo("url", url);
	query.find({
		success: function(results) {
			if (results.length > 0) {
				var counter = results[0];
				counter.fetchWhenSave(true);
				counter.increment("time");
				counter.save(null, {
					success: function(counter) {
						var content =  counter.get('time') + ' ' + $(document.getElementById(url)).text();
						$(document.getElementById(url)).text(content);
					},
					error: function(counter, error) {
						console.log('Failed to save Visitor num, with error message: ' + error.message);
					}
				});
			} else {
				var newcounter = new Counter();
				newcounter.set("title", title);
				newcounter.set("url", url);
				newcounter.set("time", 1);
				newcounter.save(null, {
					success: function(newcounter) {
					    console.log("newcounter.get('time')="+newcounter.get('time'));
						var content = newcounter.get('time') + ' ' + $(document.getElementById(url)).text();
						$(document.getElementById(url)).text(content);
					},
					error: function(newcounter, error) {
						console.log('Failed to create');
					}
				});
			}
		},
		error: function(error) {
			console.log('Error:' + error.code + " " + error.message);
		}
	});
}
$(function() {
	var Counter = AV.Object.extend("Counter");
	if ($('.leancloud_visitors').length == 1) {
		addCount(Counter);
	} else if ($('.post-title-link').length > 1) {
		showTime(Counter);
	}
}); 
</script>
  
  
<!-- mathjax config similar to math.stackexchange -->

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      tex2jax: {
        skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
      }
    });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for(i=0; i < all.length; i += 1) {
            all[i].SourceElement().parentNode.className += ' has-jax';
        }
    });
</script>

<script type="text/javascript" src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</body>
</html>
